package com.java.mvc;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @ClassName DispatcherServlet
 * @Description Servlet容器
 * @Author 0715-YuHao
 * @Date 2020/9/7 17:39
 * @Version 1.0
 */
@WebServlet(
        value = "*.do",//对所有.do的请求做响应
        initParams = {
                //配置初始化参数，存入本地配置文件uri
                @WebInitParam(
                    name = "contentConfigLocation",
                    value = "application.properties"
                )
        },
        //服务器启动时加载该Servlet
        loadOnStartup = 0
        )
public class DispatcherServlet extends HttpServlet {

    @Override
    public void init(ServletConfig config) throws ServletException {
        //1. 获取本地文件uri地址
        String path = config.getInitParameter("contentConfigLocation");
        //2. 通过类加载器获取本地配置文件输入流
        InputStream is = DispatcherServlet.class.getClassLoader().getResourceAsStream(path);
        //3，调用映射器的静态方法load(),通过反射机制获取所有控制器被注解的方法并存入Map集合
        HandlerMapping.load(is);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 获取用户请求的uri /xx.do
        String uri = req.getRequestURI();
        //2. 通过映射器查找是否存在对应映射对象
        HandlerMapping.MVCMapping mapping = HandlerMapping.get(uri);
        if (mapping == null) {
            resp.sendError(404, "自定义MVC:映射地址不存在"+uri);
            return;
        }
        //3，从映射对象中获取控制器对象、方法、注解类型
        Object obj = mapping.getObj();
        Method method = mapping.getMethod();
        Object result = null;
        try {
            //4. 执行方法并用Object接收返回结果
            result = method.invoke(obj, req, resp);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        //根据注解类型判断该方法返回结果
        switch (mapping.getType()) {
            case TEXT:
                //文本响应，将文本结果返回给客户端
                resp.getWriter().write((String) result);
                break;
            case VIEW:
                //视图响应，重定向至对应视图界面
                resp.sendRedirect((String) result);
                break;
            default:
        }
    }
}
